07 责任重构

责任重构

让代码尽量符合单一职责原则,会大大的提高阅读和维护效率

Move Method(搬移函数)

problem:有个函数与其所驻class之外的另一个class进行更多交流:调用后者,或被后者调用;可以认为这个函数更适合作为另一个class的特性。
solution:在该函数最常引用的class中建立一个有着类似行为的新函数;之后将旧函数变成一个单纯的委托函数(delegating method),或是将旧函数完全移除。

重构原因?

这个方法被另外的对象调用的更多,更适合作为另一个对象具有的功能。

什么时候需要被移动?

使用另一个对象的次数比使用自己所驻对象的次数还多。
如果真的很难做出决定,那么或许「移动这个函数与否」并不那么重要。可以先放着,以后总是可以修改的。

Move Field(搬移值域)

problem:某个field(值域〕被其所驻class之外的另一个class更多地用到。
solution:在target class 建立一个new field,修改source field的所有用户,令它们改用此new field。

重构原因?

这个字段被另一个类使用的更多,更适合作为另一个类具有的属性。

Extract Class(提炼类)

problem:某个class做了应该由两个classes做的事。
solution:建立一个新class,将相关的值域和函数从旧class搬移到新class。

重构原因?

别让一个类做太多的事情,必要的时候分离出一个新的class。

Inline Class(将类内联化)

problem:某个class没有做太多事情(没有承担足够责任)。
solution:将class的所有特性搬移到另一个class中,然后移除原class。

Hide Delegate(隐藏「委托关系」)

problem:客户端从对象A的字段或方法获取对象B.然后客户端调用对象B的方法。
solution:在类A中创建一个新方法,该方法将调用委托给对象B.现在客户端不知道或依赖于类B.

什么是委托?

客户端调用的对象获取不到信息,只能委托给第三方类来获取,这个第三方对象就叫委托类。
这种通过其他类来获取信息的方式就叫委托。

重构原因?

「封装」即使不是对象的最关键特征,也是最关键特征之一。
「封装」意味每个对象都应该尽可能少了解系统的其他部分。
如此一来,一旦发生变化,需要了解这一变化的对象就会比较少——从而使得变化比较容易进行。

Remove Middle Man(移除中间人)

problem:类有太多方法,这些方法都是委托其它对象。
solution:删除这些方法并强制客户端直接调用委托类的方法。

重构原因?

封装也是要付出代价的,它的代价就是:每当客户要使用 delegate(受托类)的新特性时,就必须在server端添加一个简单委托函数。随着delegate的特性(功能)愈来愈多,这一过程会让你痛苦不己。server 完全变成了一 个「中间人」,此时你就应该让客户直接调用delegate。

合适的隐藏程序需要随着系统相应的变化,重构的意义就在于——代码的逻辑永远不会有问题,我们要做的只是不断的修补。

Introduce Foreign Method(引入外加函数)

problem:在调用的库类中,想要增加一个函数,但是并没有代码的访问权。
solution:这时,只能再本类中新增一个函数,并把库类作为参数传入,然后实现新的功能。

1
2
3
4
5
6
7
8
9
Date newStart = new Date (previousEnd.getYear(),previousEnd.getMonth(), previousEnd.getDate() + 1);//被多次使用到

//======================after refactoring=========================

Date newStart = nextDay(previousEnd);

private static Date nextDay(Date arg) {
return new Date (arg.getYear(),arg.getMonth(), arg.getDate() + 1);
}

无法修改Date类,就在本类中新增新一个方法,使用Date辅助我们实现。

重构原因?

  1. 某个功能代码被多次使用到,这时候需要提取成方法来实现复用。
  2. 无法直接修改源码

    外加函数终归是权宜之计。如果有可能,你仍然应该将这些函数搬移到它们的理想家园。

Introduce Local Extension(引入本地扩展)

当Introduce Foreign Method需要增加的函数过多,就需要建立一个新class,使它包含这些额外函数。
让这个扩展类成为source class的subclass(子类〕或wrapper(外覆类——使用组合引入source class)。

重构原因?

如果只需要一两个函数,你可以使用Introduce Foreign Method。但如果你需要的额外函数超过两个,外加函数(foreign methods)就很难控制住它们了。所以,你需要将这些函数组织在一起,放到一个恰当地方去。要达到这一目的,标准对象技术subclassing和wrapping是显而易见的办法。这种情况下我把subclass或wrapper称为local extention(本地扩展〕。

本文标题:07 责任重构

文章作者:Sun

发布时间:2019年01月09日 - 10:01

最后更新:2019年01月17日 - 20:01

原始链接:https://sunyi720.github.io/2019/01/09/refactoring/07 责任重构/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。